package cn.tradewin.advisor.mail.services.impl;

import java.io.File;
import java.io.UnsupportedEncodingException;

import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.internet.MimeUtility;
import javax.naming.NamingException;

import org.apache.commons.mail.Email;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.HtmlEmail;
import org.apache.commons.mail.MultiPartEmail;
import org.apache.commons.mail.SimpleEmail;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.annotations.Symbol;
import org.slf4j.Logger;
import org.springframework.util.StringUtils;

import cn.tradewin.advisor.commons.AdvisorSymbols;
import cn.tradewin.advisor.mail.MailMessageHeaders;
import cn.tradewin.advisor.mail.services.MailService;

public class MailServiceImpl implements MailService<Email> {

	private final Logger log;

	private final String jndi;
	
	public MailServiceImpl(Logger log,
			@Inject @Symbol(AdvisorSymbols.MAIL_SESSION_JNDI) String jndi) {
		this.log = log;
		this.jndi = jndi;
	}

	@Override
	public boolean sendHtmlMail(MailMessageHeaders headers, String htmlBody) {
		return sendHtmlMail(headers, htmlBody, (DataSource[]) null);
	}

	@Override
	public boolean sendHtmlMail(MailMessageHeaders headers, String htmlBody,
			File... attachments) {
		DataSource[] dataSources = null;
		if (attachments != null) {
			dataSources = new DataSource[attachments.length];
			for (int x = 0; x < attachments.length; x++) {
				dataSources[x] = new FileDataSource(attachments[x]);
			}
		}
		return sendHtmlMail(headers, htmlBody, dataSources);
	}

	@Override
	public boolean sendHtmlMail(MailMessageHeaders headers, String htmlBody,
			DataSource... dataSources) {
		try {
			HtmlEmail email = new HtmlEmail();
			email.setMailSessionFromJNDI(jndi);

			setMailMessageHeaders(email, headers);

			if (dataSources != null) {
				for (DataSource dataSource : dataSources) {
					email.attach(dataSource, dataSource.getName(),
							dataSource.getName());
				}
			}
			email.setCharset(headers.getCharset());
			email.setHtmlMsg(htmlBody);

			String msgId = email.send();
			log.debug("email message id = " + msgId);

			return true;
		} catch (NamingException e) {
			log.equals(e.getMessage());
			throw new RuntimeException(e);
		} catch (EmailException e) {
			// FIXME Handle gracefully
			log.equals(e.getMessage());
			throw new RuntimeException(e);
		}
	}

	@Override
	public boolean sendPlainTextMail(MailMessageHeaders headers, String body) {
		return sendPlainTextMail(headers, body, (DataSource[]) null);
	}

	@Override
	public boolean sendPlainTextMail(MailMessageHeaders headers, String body,
			File... attachments) {
		DataSource[] dataSources = null;

		if (attachments != null) {
			dataSources = new DataSource[attachments.length];
			for (int x = 0; x < attachments.length; x++) {
				dataSources[x] = new FileDataSource(attachments[x]);
			}
		}

		return sendPlainTextMail(headers, body, dataSources);
	}

	@Override
	public boolean sendPlainTextMail(MailMessageHeaders headers, String body,
			DataSource... dataSources) {
		try {
			Email email = null;

			if (dataSources != null && dataSources.length > 0) {
				MultiPartEmail multiPart = new MultiPartEmail();
				for (DataSource dataSource : dataSources) {
					multiPart.attach(dataSource, dataSource.getName(),
							dataSource.getName());
				}
				email = multiPart;
			} else {
				email = new SimpleEmail();
			}
			email.setMailSessionFromJNDI(jndi);
			setMailMessageHeaders(email, headers);
			email.setCharset(headers.getCharset());
			try {
				email.setMsg(new String(body.getBytes(), headers.getCharset()));
			} catch (UnsupportedEncodingException e) {
				throw new RuntimeException(e);
			}

			String msgId = email.send();
			log.debug("email message id = " + msgId);
			return true;
		} catch (NamingException e) {
			log.error(e.getMessage());
			throw new RuntimeException(e);
		} catch (EmailException e) {
			// FIXME Handle gracefully
			log.error(e.getMessage());
			throw new RuntimeException(e);

		}
	}

	private void setMailMessageHeaders(Email email, MailMessageHeaders headers)
			throws EmailException {
		
		if (!StringUtils.isEmpty(headers.getFrom())) {
			email.setFrom(headers.getFrom());
		} else {
			email.setFrom(email.getMailSession().getProperty("mail.from"));
		}

		try {
			email.setSubject(MimeUtility.encodeText(headers.getSubject(),
					headers.getCharset(), null));
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}

		for (String to : headers.getTo()) {
			email.addTo(to);
		}

		for (String cc : headers.getCc()) {
			email.addCc(cc);
		}

		for (String bcc : headers.getBcc()) {
			email.addBcc(bcc);
		}
	}

}
